import { ref, watch } from 'vue';
import { get, isEqual, uniqueId } from 'lodash-es';
import { viewImages } from '../img-viewer/viewer.js';
import env from '../../env.js';

const uploadUrl = '/fileservice/v1/fileYd';
export const action = env.DEV ? env.get('VUE_APP_API_BASE_URL') + uploadUrl : uploadUrl;

export const acceptTypes = {
  image: 'image/gif, image/png, image/jpeg, image/bmp, image/webp',
  video: 'video/mp4, video/mpeg, video/webm, video/ogg, video/x-flv, video/x-msvideo',
  audio: 'audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav, audio/x-m4a, audio/x-mpegurl',
  doc: 'text/plain, application/pdf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
};

export function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onerror = (error) => reject(error);
    reader.onload = () => resolve(reader.result);
    reader.readAsDataURL(file);
  });
}

export function getSuffix(str) {
  return str.replace(/.+(\.(\w+))$/, ($0, $1, $2) => $2);
}

export function getAcceptTypes(accepts) {
  if (typeof accepts === 'string') {
    return acceptTypes[accepts];
  }
  if (Array.isArray(accepts)) {
    return accepts.map((item) => acceptTypes[item]).join(',');
  }
}

export function formatValues(values) {
  // '图片地址,图片地址' or ['图片地址','图片地址'] or [{uid: '',name: '',status: '',url: ''},...]
  if (typeof values === 'string') {
    values = values.split(',');
  }
  if (!Array.isArray(values)) {
    values = [];
  }
  values = values.filter((item) => {
    return typeof item === 'string' || (typeof item === 'object' && item && item.url);
  });
  return values.map((item) => {
    if (typeof item === 'string') {
      return { uid: uniqueId(), name: getSuffix(item), url: item, status: 'done' };
    }
    return {
      ...item,
      uid: item.uid || uniqueId(),
      name: item.name || getSuffix(item.url) || '未命名',
      url: item.url || null,
      status: 'done',
    };
  });
}

export function formatFiles(fileList) {
  fileList = fileList.map((item) => get(item, 'url') || get(item, 'response.url'));
  return fileList.filter(Boolean).join(',');
}

export function handleUploadChange(info) {
  let resFileList = [...info.fileList];
  resFileList = resFileList.map((file) => {
    if (file.response) {
      file.url = file.response.url;
    }
    return file;
  });

  return resFileList;
}

export async function handleUploadPreview(file) {
  if (!file.url && !file.preview) {
    file.preview = await getBase64(file.originFileObj);
  }
  viewImages(file.url || file.preview);
}

export const uploadProps = {
  modelValue: { type: String, default: undefined },
  maxCount: { type: Number, default: 1 },
  accept: { type: [String, Array], default: 'image' },
};

export function useUploader(props, ctx) {
  let accept = getAcceptTypes(props.accept);
  let fileList = ref([]);

  watch(
    () => props.modelValue,
    (values) => {
      if (typeof values === 'string') {
        values = values.split(',');
      }
      values = formatValues(values);
      if (!isEqual(fileList.value, values)) {
        fileList.value = values;
      }
    },
    { immediate: true }
  );

  function onChange(info) {
    let resFileList = handleUploadChange(info);
    let files = resFileList.slice(-1 * props.maxCount);
    let values = formatFiles(files);
    fileList.value = files;

    if (!isEqual(props.modelValue, values)) {
      ctx.emit('update:modelValue', values);
    }
  }

  return { action, fileList, accept, onChange, onPreview: handleUploadPreview };
}
